/**
 * PHOSIDE: PHosphorylation Site IDentification Engine.
 * Copyright 2009 Digital Biology Lab, University of Missouri.
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 3 of the License, or (at your option) any later
 * version. <p/> This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the License for more
 * details.
 */

package phoside.io.fasta;

import java.util.Set;

import phoside.Protein;
import phoside.ProteinImpl;
import phoside.Proteins;

import phoside.io.fasta.parser.DefaultHeaderParser;
import phoside.io.fasta.parser.DefaultSequenceParser;
import phoside.io.fasta.parser.HeaderParser;
import phoside.io.fasta.parser.HeaderRule;
import phoside.io.fasta.parser.SequenceParser;

import phoside.io.fasta.util.FastaVisitor;

/**
 *
 * @author gjj
 */
public class ProteinsReaderFastaVisitor implements FastaVisitor {
    protected final Proteins proteins;
    protected final HeaderParser headerParser;
    protected final SequenceParser sequenceParser;
    protected final Set<String> accessions;
    protected final boolean include;
    protected Proteins.ConfictHandleOption confictHandleOption;

    public ProteinsReaderFastaVisitor(final Proteins proteins,
            final HeaderRule rule) {
        this(proteins, rule, null);
    }

    public ProteinsReaderFastaVisitor(final Proteins proteins,
                                      final HeaderRule rule,
                                      final Set<String> accessions) {
        this(proteins, rule, accessions, true);
    }

    public ProteinsReaderFastaVisitor(final Proteins proteins,
                                      final HeaderRule rule,
                                      final Set<String> accessions,
                                      final boolean include) {
        this(proteins, new DefaultHeaderParser(rule), accessions, include);
    }

    public ProteinsReaderFastaVisitor(final Proteins proteins,
                                      final DefaultHeaderParser parser) {
        this(proteins, parser, (Set)null);
    }

    public ProteinsReaderFastaVisitor(final Proteins proteins,
                                      final HeaderParser headParser,
                                      final SequenceParser sequenceParser) {
        this(proteins, headParser, sequenceParser, null);
    }

    public ProteinsReaderFastaVisitor(final Proteins proteins,
                                      final HeaderParser headParser,
                                      final SequenceParser sequenceParser,
                                      final Set<String> accessions) {
        this(proteins, headParser, sequenceParser, accessions, true);
    }

    public ProteinsReaderFastaVisitor(final Proteins proteins,
                                      final HeaderParser headParser,
                                      final Set<String> accessions) {
        this(proteins, headParser, accessions, true);
    }

    public ProteinsReaderFastaVisitor(final Proteins proteins,
                                      final HeaderParser headParser,
                                      final Set<String> accessions,
                                      final boolean include) {
        this(proteins, headParser, new DefaultSequenceParser(), accessions, include);
    }

    public ProteinsReaderFastaVisitor(final Proteins proteins,
                                      final HeaderParser headParser,
                                      final SequenceParser sequenceParser,
                                      final Set<String> accessions,
                                      final boolean include) {
        if (headParser==null) {
            throw new NullPointerException();
        }

        this.proteins = proteins;
        this.headerParser = headParser;
        this.accessions = accessions;
        this.include = include;
        this.sequenceParser = sequenceParser;
        confictHandleOption = Proteins.ConfictHandleOption.RENAME;
    }

    public void setConfictHandleOption(Proteins.ConfictHandleOption confictHandleOption) {
        this.confictHandleOption = confictHandleOption;
    }

    /**
     * 
     * @param header
     * @param sequence
     */
    public void visit(final String header, final String sequence) {
        if (header==null || sequence==null) {
            throw new NullPointerException("Null header or sequence.");
        }

        headerParser.parse(header);
        String accession = headerParser.getAccession();
        if (accession == null) return;
        if (accessions!=null && include!=accessions.contains(accession)) return;

        String name = headerParser.getSymbol();
        String description = headerParser.getDescription();
        String species = headerParser.getSpecies();

        sequenceParser.parse(sequence);
        String proSeq = sequenceParser.getSequence();
        Protein protein = new ProteinImpl(accession, proSeq, name, description, species);

        proteins.addProtein(protein, confictHandleOption);
    }

    public Proteins getProteins() {
        return proteins;
    }

}
